/*!
 * Draggabilly PACKAGED v2.1.1
 * Make that shiz draggable
 * http://draggabilly.desandro.com
 * MIT license
 */

/**
 * Bridget makes jQuery widgets
 * v2.0.0
 * MIT license
 */

/* jshint browser: true, strict: true, undef: true, unused: true */

(function(window, factory) {
  /* globals define: false, module: false, require: false */

  if (typeof define == "function" && define.amd) {
    // AMD
    define("jquery-bridget/jquery-bridget", ["jquery"], function(jQuery) {
      factory(window, jQuery);
    });
  } else if (typeof module == "object" && module.exports) {
    // CommonJS
    module.exports = factory(window, require("jquery"));
  } else {
    // browser global
    window.jQueryBridget = factory(window, window.jQuery);
  }
})(window, function factory(window, jQuery) {
  // ----- utils ----- //

  var arraySlice = Array.prototype.slice;

  // helper function for logging errors
  // $.error breaks jQuery chaining
  var console = window.console;
  var logError =
    typeof console == "undefined"
      ? function() {}
      : function(message) {
          console.error(message);
        };

  // ----- jQueryBridget ----- //

  function jQueryBridget(namespace, PluginClass, $) {
    $ = $ || jQuery || window.jQuery;
    if (!$) {
      return;
    }

    // add option method -> $().plugin('option', {...})
    if (!PluginClass.prototype.option) {
      // option setter
      PluginClass.prototype.option = function(opts) {
        // bail out if not an object
        if (!$.isPlainObject(opts)) {
          return;
        }
        this.options = $.extend(true, this.options, opts);
      };
    }

    // make jQuery plugin
    $.fn[namespace] = function(arg0 /*, arg1 */) {
      if (typeof arg0 == "string") {
        // method call $().plugin( 'methodName', { options } )
        // shift arguments by 1
        var args = arraySlice.call(arguments, 1);
        return methodCall(this, arg0, args);
      }
      // just $().plugin({ options })
      plainCall(this, arg0);
      return this;
    };

    // $().plugin('methodName')
    function methodCall($elems, methodName, args) {
      var returnValue;
      var pluginMethodStr = "$()." + namespace + '("' + methodName + '")';

      $elems.each(function(i, elem) {
        // get instance
        var instance = $.data(elem, namespace);
        if (!instance) {
          logError(
            namespace +
              " not initialized. Cannot call methods, i.e. " +
              pluginMethodStr
          );
          return;
        }

        var method = instance[methodName];
        if (!method || methodName.charAt(0) == "_") {
          logError(pluginMethodStr + " is not a valid method");
          return;
        }

        // apply method, get return value
        var value = method.apply(instance, args);
        // set return value if value is returned, use only first value
        returnValue = returnValue === undefined ? value : returnValue;
      });

      return returnValue !== undefined ? returnValue : $elems;
    }

    function plainCall($elems, options) {
      $elems.each(function(i, elem) {
        var instance = $.data(elem, namespace);
        if (instance) {
          // set options & init
          instance.option(options);
          instance._init();
        } else {
          // initialize new instance
          instance = new PluginClass(elem, options);
          $.data(elem, namespace, instance);
        }
      });
    }

    updateJQuery($);
  }

  // ----- updateJQuery ----- //

  // set $.bridget for v1 backwards compatibility
  function updateJQuery($) {
    if (!$ || ($ && $.bridget)) {
      return;
    }
    $.bridget = jQueryBridget;
  }

  updateJQuery(jQuery || window.jQuery);

  // -----  ----- //

  return jQueryBridget;
});

/*!
 * getSize v2.0.2
 * measure size of elements
 * MIT license
 */

/*jshint browser: true, strict: true, undef: true, unused: true */
/*global define: false, module: false, console: false */

(function(window, factory) {
  if (typeof define == "function" && define.amd) {
    // AMD
    define("get-size/get-size", [], function() {
      return factory();
    });
  } else if (typeof module == "object" && module.exports) {
    // CommonJS
    module.exports = factory();
  } else {
    // browser global
    window.getSize = factory();
  }
})(window, function factory() {
  // -------------------------- helpers -------------------------- //

  // get a number from a string, not a percentage
  function getStyleSize(value) {
    var num = parseFloat(value);
    // not a percent like '100%', and a number
    var isValid = value.indexOf("%") == -1 && !isNaN(num);
    return isValid && num;
  }

  function noop() {}

  var logError =
    typeof console == "undefined"
      ? noop
      : function(message) {
          console.error(message);
        };

  // -------------------------- measurements -------------------------- //

  var measurements = [
    "paddingLeft",
    "paddingRight",
    "paddingTop",
    "paddingBottom",
    "marginLeft",
    "marginRight",
    "marginTop",
    "marginBottom",
    "borderLeftWidth",
    "borderRightWidth",
    "borderTopWidth",
    "borderBottomWidth"
  ];

  var measurementsLength = measurements.length;

  function getZeroSize() {
    var size = {
      width: 0,
      height: 0,
      innerWidth: 0,
      innerHeight: 0,
      outerWidth: 0,
      outerHeight: 0
    };
    for (var i = 0; i < measurementsLength; i++) {
      var measurement = measurements[i];
      size[measurement] = 0;
    }
    return size;
  }

  // -------------------------- getStyle -------------------------- //

  /**
   * getStyle, get style of element, check for Firefox bug
   * https://bugzilla.mozilla.org/show_bug.cgi?id=548397
   */
  function getStyle(elem) {
    var style = getComputedStyle(elem);
    if (!style) {
      logError(
        "Style returned " +
          style +
          ". Are you running this code in a hidden iframe on Firefox? " +
          "See http://bit.ly/getsizebug1"
      );
    }
    return style;
  }

  // -------------------------- setup -------------------------- //

  var isSetup = false;

  var isBoxSizeOuter;

  /**
   * setup
   * check isBoxSizerOuter
   * do on first getSize() rather than on page load for Firefox bug
   */
  function setup() {
    // setup once
    if (isSetup) {
      return;
    }
    isSetup = true;

    // -------------------------- box sizing -------------------------- //

    /**
     * WebKit measures the outer-width on style.width on border-box elems
     * IE & Firefox<29 measures the inner-width
     */
    var div = document.createElement("div");
    div.style.width = "200px";
    div.style.padding = "1px 2px 3px 4px";
    div.style.borderStyle = "solid";
    div.style.borderWidth = "1px 2px 3px 4px";
    div.style.boxSizing = "border-box";

    var body = document.body || document.documentElement;
    body.appendChild(div);
    var style = getStyle(div);

    getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize(style.width) == 200;
    body.removeChild(div);
  }

  // -------------------------- getSize -------------------------- //

  function getSize(elem) {
    setup();

    // use querySeletor if elem is string
    if (typeof elem == "string") {
      elem = document.querySelector(elem);
    }

    // do not proceed on non-objects
    if (!elem || typeof elem != "object" || !elem.nodeType) {
      return;
    }

    var style = getStyle(elem);

    // if hidden, everything is 0
    if (style.display == "none") {
      return getZeroSize();
    }

    var size = {};
    size.width = elem.offsetWidth;
    size.height = elem.offsetHeight;

    var isBorderBox = (size.isBorderBox = style.boxSizing == "border-box");

    // get all measurements
    for (var i = 0; i < measurementsLength; i++) {
      var measurement = measurements[i];
      var value = style[measurement];
      var num = parseFloat(value);
      // any 'auto', 'medium' value will be 0
      size[measurement] = !isNaN(num) ? num : 0;
    }

    var paddingWidth = size.paddingLeft + size.paddingRight;
    var paddingHeight = size.paddingTop + size.paddingBottom;
    var marginWidth = size.marginLeft + size.marginRight;
    var marginHeight = size.marginTop + size.marginBottom;
    var borderWidth = size.borderLeftWidth + size.borderRightWidth;
    var borderHeight = size.borderTopWidth + size.borderBottomWidth;

    var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter;

    // overwrite width and height if we can get it from style
    var styleWidth = getStyleSize(style.width);
    if (styleWidth !== false) {
      size.width =
        styleWidth +
        // add padding and border unless it's already including it
        (isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth);
    }

    var styleHeight = getStyleSize(style.height);
    if (styleHeight !== false) {
      size.height =
        styleHeight +
        // add padding and border unless it's already including it
        (isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight);
    }

    size.innerWidth = size.width - (paddingWidth + borderWidth);
    size.innerHeight = size.height - (paddingHeight + borderHeight);

    size.outerWidth = size.width + marginWidth;
    size.outerHeight = size.height + marginHeight;

    return size;
  }

  return getSize;
});

/**
 * EvEmitter v1.0.3
 * Lil' event emitter
 * MIT License
 */

/* jshint unused: true, undef: true, strict: true */

(function(global, factory) {
  // universal module definition
  /* jshint strict: false */ /* globals define, module, window */
  if (typeof define == "function" && define.amd) {
    // AMD - RequireJS
    define("ev-emitter/ev-emitter", factory);
  } else if (typeof module == "object" && module.exports) {
    // CommonJS - Browserify, Webpack
    module.exports = factory();
  } else {
    // Browser globals
    global.EvEmitter = factory();
  }
})(typeof window != "undefined" ? window : this, function() {
  function EvEmitter() {}

  var proto = EvEmitter.prototype;

  proto.on = function(eventName, listener) {
    if (!eventName || !listener) {
      return;
    }
    // set events hash
    var events = (this._events = this._events || {});
    // set listeners array
    var listeners = (events[eventName] = events[eventName] || []);
    // only add once
    if (listeners.indexOf(listener) == -1) {
      listeners.push(listener);
    }

    return this;
  };

  proto.once = function(eventName, listener) {
    if (!eventName || !listener) {
      return;
    }
    // add event
    this.on(eventName, listener);
    // set once flag
    // set onceEvents hash
    var onceEvents = (this._onceEvents = this._onceEvents || {});
    // set onceListeners object
    var onceListeners = (onceEvents[eventName] = onceEvents[eventName] || {});
    // set flag
    onceListeners[listener] = true;

    return this;
  };

  proto.off = function(eventName, listener) {
    var listeners = this._events && this._events[eventName];
    if (!listeners || !listeners.length) {
      return;
    }
    var index = listeners.indexOf(listener);
    if (index != -1) {
      listeners.splice(index, 1);
    }

    return this;
  };

  proto.emitEvent = function(eventName, args) {
    var listeners = this._events && this._events[eventName];
    if (!listeners || !listeners.length) {
      return;
    }
    var i = 0;
    var listener = listeners[i];
    args = args || [];
    // once stuff
    var onceListeners = this._onceEvents && this._onceEvents[eventName];

    while (listener) {
      var isOnce = onceListeners && onceListeners[listener];
      if (isOnce) {
        // remove listener
        // remove before trigger to prevent recursion
        this.off(eventName, listener);
        // unset once flag
        delete onceListeners[listener];
      }
      // trigger listener
      listener.apply(this, args);
      // get next listener
      i += isOnce ? 0 : 1;
      listener = listeners[i];
    }

    return this;
  };

  return EvEmitter;
});

/*!
 * Unipointer v2.1.0
 * base class for doing one thing with pointer event
 * MIT license
 */

/*jshint browser: true, undef: true, unused: true, strict: true */

(function(window, factory) {
  // universal module definition
  /* jshint strict: false */ /*global define, module, require */
  if (typeof define == "function" && define.amd) {
    // AMD
    define("unipointer/unipointer", ["ev-emitter/ev-emitter"], function(
      EvEmitter
    ) {
      return factory(window, EvEmitter);
    });
  } else if (typeof module == "object" && module.exports) {
    // CommonJS
    module.exports = factory(window, require("ev-emitter"));
  } else {
    // browser global
    window.Unipointer = factory(window, window.EvEmitter);
  }
})(window, function factory(window, EvEmitter) {
  function noop() {}

  function Unipointer() {}

  // inherit EvEmitter
  var proto = (Unipointer.prototype = Object.create(EvEmitter.prototype));

  proto.bindStartEvent = function(elem) {
    this._bindStartEvent(elem, true);
  };

  proto.unbindStartEvent = function(elem) {
    this._bindStartEvent(elem, false);
  };

  /**
   * works as unbinder, as you can ._bindStart( false ) to unbind
   * @param {Boolean} isBind - will unbind if falsey
   */
  proto._bindStartEvent = function(elem, isBind) {
    // munge isBind, default to true
    isBind = isBind === undefined ? true : !!isBind;
    var bindMethod = isBind ? "addEventListener" : "removeEventListener";

    if (window.navigator.pointerEnabled) {
      // W3C Pointer Events, IE11. See https://coderwall.com/p/mfreca
      elem[bindMethod]("pointerdown", this);
    } else if (window.navigator.msPointerEnabled) {
      // IE10 Pointer Events
      elem[bindMethod]("MSPointerDown", this);
    } else {
      // listen for both, for devices like Chrome Pixel
      elem[bindMethod]("mousedown", this);
      elem[bindMethod]("touchstart", this);
    }
  };

  // trigger handler methods for events
  proto.handleEvent = function(event) {
    var method = "on" + event.type;
    if (this[method]) {
      this[method](event);
    }
  };

  // returns the touch that we're keeping track of
  proto.getTouch = function(touches) {
    for (var i = 0; i < touches.length; i++) {
      var touch = touches[i];
      if (touch.identifier == this.pointerIdentifier) {
        return touch;
      }
    }
  };

  // ----- start event ----- //

  proto.onmousedown = function(event) {
    // dismiss clicks from right or middle buttons
    var button = event.button;
    if (button && (button !== 0 && button !== 1)) {
      return;
    }
    this._pointerDown(event, event);
  };

  proto.ontouchstart = function(event) {
    this._pointerDown(event, event.changedTouches[0]);
  };

  proto.onMSPointerDown = proto.onpointerdown = function(event) {
    this._pointerDown(event, event);
  };

  /**
   * pointer start
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto._pointerDown = function(event, pointer) {
    // dismiss other pointers
    if (this.isPointerDown) {
      return;
    }

    this.isPointerDown = true;
    // save pointer identifier to match up touch events
    this.pointerIdentifier =
      pointer.pointerId !== undefined
        ? // pointerId for pointer events, touch.indentifier for touch events
          pointer.pointerId
        : pointer.identifier;

    this.pointerDown(event, pointer);
  };

  proto.pointerDown = function(event, pointer) {
    this._bindPostStartEvents(event);
    this.emitEvent("pointerDown", [event, pointer]);
  };

  // hash of events to be bound after start event
  var postStartEvents = {
    mousedown: ["mousemove", "mouseup"],
    touchstart: ["touchmove", "touchend", "touchcancel"],
    pointerdown: ["pointermove", "pointerup", "pointercancel"],
    MSPointerDown: ["MSPointerMove", "MSPointerUp", "MSPointerCancel"]
  };

  proto._bindPostStartEvents = function(event) {
    if (!event) {
      return;
    }
    // get proper events to match start event
    var events = postStartEvents[event.type];
    // bind events to node
    events.forEach(function(eventName) {
      window.addEventListener(eventName, this);
    }, this);
    // save these arguments
    this._boundPointerEvents = events;
  };

  proto._unbindPostStartEvents = function() {
    // check for _boundEvents, in case dragEnd triggered twice (old IE8 bug)
    if (!this._boundPointerEvents) {
      return;
    }
    this._boundPointerEvents.forEach(function(eventName) {
      window.removeEventListener(eventName, this);
    }, this);

    delete this._boundPointerEvents;
  };

  // ----- move event ----- //

  proto.onmousemove = function(event) {
    this._pointerMove(event, event);
  };

  proto.onMSPointerMove = proto.onpointermove = function(event) {
    if (event.pointerId == this.pointerIdentifier) {
      this._pointerMove(event, event);
    }
  };

  proto.ontouchmove = function(event) {
    var touch = this.getTouch(event.changedTouches);
    if (touch) {
      this._pointerMove(event, touch);
    }
  };

  /**
   * pointer move
   * @param {Event} event
   * @param {Event or Touch} pointer
   * @private
   */
  proto._pointerMove = function(event, pointer) {
    this.pointerMove(event, pointer);
  };

  // public
  proto.pointerMove = function(event, pointer) {
    this.emitEvent("pointerMove", [event, pointer]);
  };

  // ----- end event ----- //

  proto.onmouseup = function(event) {
    this._pointerUp(event, event);
  };

  proto.onMSPointerUp = proto.onpointerup = function(event) {
    if (event.pointerId == this.pointerIdentifier) {
      this._pointerUp(event, event);
    }
  };

  proto.ontouchend = function(event) {
    var touch = this.getTouch(event.changedTouches);
    if (touch) {
      this._pointerUp(event, touch);
    }
  };

  /**
   * pointer up
   * @param {Event} event
   * @param {Event or Touch} pointer
   * @private
   */
  proto._pointerUp = function(event, pointer) {
    this._pointerDone();
    this.pointerUp(event, pointer);
  };

  // public
  proto.pointerUp = function(event, pointer) {
    this.emitEvent("pointerUp", [event, pointer]);
  };

  // ----- pointer done ----- //

  // triggered on pointer up & pointer cancel
  proto._pointerDone = function() {
    // reset properties
    this.isPointerDown = false;
    delete this.pointerIdentifier;
    // remove events
    this._unbindPostStartEvents();
    this.pointerDone();
  };

  proto.pointerDone = noop;

  // ----- pointer cancel ----- //

  proto.onMSPointerCancel = proto.onpointercancel = function(event) {
    if (event.pointerId == this.pointerIdentifier) {
      this._pointerCancel(event, event);
    }
  };

  proto.ontouchcancel = function(event) {
    var touch = this.getTouch(event.changedTouches);
    if (touch) {
      this._pointerCancel(event, touch);
    }
  };

  /**
   * pointer cancel
   * @param {Event} event
   * @param {Event or Touch} pointer
   * @private
   */
  proto._pointerCancel = function(event, pointer) {
    this._pointerDone();
    this.pointerCancel(event, pointer);
  };

  // public
  proto.pointerCancel = function(event, pointer) {
    this.emitEvent("pointerCancel", [event, pointer]);
  };

  // -----  ----- //

  // utility function for getting x/y coords from event
  Unipointer.getPointerPoint = function(pointer) {
    return {
      x: pointer.pageX,
      y: pointer.pageY
    };
  };

  // -----  ----- //

  return Unipointer;
});

/*!
 * Unidragger v2.1.0
 * Draggable base class
 * MIT license
 */

/*jshint browser: true, unused: true, undef: true, strict: true */

(function(window, factory) {
  // universal module definition
  /*jshint strict: false */ /*globals define, module, require */

  if (typeof define == "function" && define.amd) {
    // AMD
    define("unidragger/unidragger", ["unipointer/unipointer"], function(
      Unipointer
    ) {
      return factory(window, Unipointer);
    });
  } else if (typeof module == "object" && module.exports) {
    // CommonJS
    module.exports = factory(window, require("unipointer"));
  } else {
    // browser global
    window.Unidragger = factory(window, window.Unipointer);
  }
})(window, function factory(window, Unipointer) {
  // -----  ----- //

  function noop() {}

  // -------------------------- Unidragger -------------------------- //

  function Unidragger() {}

  // inherit Unipointer & EvEmitter
  var proto = (Unidragger.prototype = Object.create(Unipointer.prototype));

  // ----- bind start ----- //

  proto.bindHandles = function() {
    this._bindHandles(true);
  };

  proto.unbindHandles = function() {
    this._bindHandles(false);
  };

  var navigator = window.navigator;
  /**
   * works as unbinder, as you can .bindHandles( false ) to unbind
   * @param {Boolean} isBind - will unbind if falsey
   */
  proto._bindHandles = function(isBind) {
    // munge isBind, default to true
    isBind = isBind === undefined ? true : !!isBind;
    // extra bind logic
    var binderExtra;
    if (navigator.pointerEnabled) {
      binderExtra = function(handle) {
        // disable scrolling on the element
        handle.style.touchAction = isBind ? "none" : "";
      };
    } else if (navigator.msPointerEnabled) {
      binderExtra = function(handle) {
        // disable scrolling on the element
        handle.style.msTouchAction = isBind ? "none" : "";
      };
    } else {
      binderExtra = noop;
    }
    // bind each handle
    var bindMethod = isBind ? "addEventListener" : "removeEventListener";
    for (var i = 0; i < this.handles.length; i++) {
      var handle = this.handles[i];
      this._bindStartEvent(handle, isBind);
      binderExtra(handle);
      handle[bindMethod]("click", this);
    }
  };

  // ----- start event ----- //

  /**
   * pointer start
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerDown = function(event, pointer) {
    // dismiss range sliders
    if (event.target.nodeName == "INPUT" && event.target.type == "range") {
      // reset pointerDown logic
      this.isPointerDown = false;
      delete this.pointerIdentifier;
      return;
    }

    this._dragPointerDown(event, pointer);
    // kludge to blur focused inputs in dragger
    var focused = document.activeElement;
    if (focused && focused.blur) {
      focused.blur();
    }
    // bind move and end events
    this._bindPostStartEvents(event);
    this.emitEvent("pointerDown", [event, pointer]);
  };

  // base pointer down logic
  proto._dragPointerDown = function(event, pointer) {
    // track to see when dragging starts
    this.pointerDownPoint = Unipointer.getPointerPoint(pointer);

    var canPreventDefault = this.canPreventDefaultOnPointerDown(event, pointer);
    if (canPreventDefault) {
      event.preventDefault();
    }
  };

  // overwriteable method so Flickity can prevent for scrolling
  proto.canPreventDefaultOnPointerDown = function(event) {
    // prevent default, unless touchstart or <select>
    return event.target.nodeName != "SELECT";
  };

  // ----- move event ----- //

  /**
   * drag move
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerMove = function(event, pointer) {
    var moveVector = this._dragPointerMove(event, pointer);
    this.emitEvent("pointerMove", [event, pointer, moveVector]);
    this._dragMove(event, pointer, moveVector);
  };

  // base pointer move logic
  proto._dragPointerMove = function(event, pointer) {
    var movePoint = Unipointer.getPointerPoint(pointer);
    var moveVector = {
      x: movePoint.x - this.pointerDownPoint.x,
      y: movePoint.y - this.pointerDownPoint.y
    };
    // start drag if pointer has moved far enough to start drag
    if (!this.isDragging && this.hasDragStarted(moveVector)) {
      this._dragStart(event, pointer);
    }
    return moveVector;
  };

  // condition if pointer has moved far enough to start drag
  proto.hasDragStarted = function(moveVector) {
    return Math.abs(moveVector.x) > 3 || Math.abs(moveVector.y) > 3;
  };

  // ----- end event ----- //

  /**
   * pointer up
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerUp = function(event, pointer) {
    this.emitEvent("pointerUp", [event, pointer]);
    this._dragPointerUp(event, pointer);
  };

  proto._dragPointerUp = function(event, pointer) {
    if (this.isDragging) {
      this._dragEnd(event, pointer);
    } else {
      // pointer didn't move enough for drag to start
      this._staticClick(event, pointer);
    }
  };

  // -------------------------- drag -------------------------- //

  // dragStart
  proto._dragStart = function(event, pointer) {
    this.isDragging = true;
    this.dragStartPoint = Unipointer.getPointerPoint(pointer);
    // prevent clicks
    this.isPreventingClicks = true;

    this.dragStart(event, pointer);
  };

  proto.dragStart = function(event, pointer) {
    this.emitEvent("dragStart", [event, pointer]);
  };

  // dragMove
  proto._dragMove = function(event, pointer, moveVector) {
    // do not drag if not dragging yet
    if (!this.isDragging) {
      return;
    }

    this.dragMove(event, pointer, moveVector);
  };

  proto.dragMove = function(event, pointer, moveVector) {
    event.preventDefault();
    this.emitEvent("dragMove", [event, pointer, moveVector]);
  };

  // dragEnd
  proto._dragEnd = function(event, pointer) {
    // set flags
    this.isDragging = false;
    // re-enable clicking async
    setTimeout(
      function() {
        delete this.isPreventingClicks;
      }.bind(this)
    );

    this.dragEnd(event, pointer);
  };

  proto.dragEnd = function(event, pointer) {
    this.emitEvent("dragEnd", [event, pointer]);
  };

  // ----- onclick ----- //

  // handle all clicks and prevent clicks when dragging
  proto.onclick = function(event) {
    if (this.isPreventingClicks) {
      event.preventDefault();
    }
  };

  // ----- staticClick ----- //

  // triggered after pointer down & up with no/tiny movement
  proto._staticClick = function(event, pointer) {
    // ignore emulated mouse up clicks
    if (this.isIgnoringMouseUp && event.type == "mouseup") {
      return;
    }

    // allow click in <input>s and <textarea>s
    var nodeName = event.target.nodeName;
    if (nodeName == "INPUT" || nodeName == "TEXTAREA") {
      event.target.focus();
    }
    this.staticClick(event, pointer);

    // set flag for emulated clicks 300ms after touchend
    if (event.type != "mouseup") {
      this.isIgnoringMouseUp = true;
      // reset flag after 300ms
      setTimeout(
        function() {
          delete this.isIgnoringMouseUp;
        }.bind(this),
        400
      );
    }
  };

  proto.staticClick = function(event, pointer) {
    this.emitEvent("staticClick", [event, pointer]);
  };

  // ----- utils ----- //

  Unidragger.getPointerPoint = Unipointer.getPointerPoint;

  // -----  ----- //

  return Unidragger;
});

/*!
 * Draggabilly v2.1.1
 * Make that shiz draggable
 * http://draggabilly.desandro.com
 * MIT license
 */

/*jshint browser: true, strict: true, undef: true, unused: true */

(function(window, factory) {
  // universal module definition
  /* jshint strict: false */ /*globals define, module, require */
  if (typeof define == "function" && define.amd) {
    // AMD
    define(["get-size/get-size", "unidragger/unidragger"], function(
      getSize,
      Unidragger
    ) {
      return factory(window, getSize, Unidragger);
    });
  } else if (typeof module == "object" && module.exports) {
    // CommonJS
    module.exports = factory(
      window,
      require("get-size"),
      require("unidragger")
    );
  } else {
    // browser global
    window.Draggabilly = factory(window, window.getSize, window.Unidragger);
  }
})(window, function factory(window, getSize, Unidragger) {
  // vars
  var document = window.document;

  function noop() {}

  // -------------------------- helpers -------------------------- //

  // extend objects
  function extend(a, b) {
    for (var prop in b) {
      a[prop] = b[prop];
    }
    return a;
  }

  function isElement(obj) {
    return obj instanceof HTMLElement;
  }

  // -------------------------- requestAnimationFrame -------------------------- //

  // get rAF, prefixed, if present
  var requestAnimationFrame =
    window.requestAnimationFrame ||
    window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame;

  // fallback to setTimeout
  var lastTime = 0;
  if (!requestAnimationFrame) {
    requestAnimationFrame = function(callback) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = setTimeout(callback, timeToCall);
      lastTime = currTime + timeToCall;
      return id;
    };
  }

  // -------------------------- support -------------------------- //

  var docElem = document.documentElement;
  var transformProperty =
    typeof docElem.style.transform == "string"
      ? "transform"
      : "WebkitTransform";

  var jQuery = window.jQuery;

  // --------------------------  -------------------------- //

  function Draggabilly(element, options) {
    // querySelector if string
    this.element =
      typeof element == "string" ? document.querySelector(element) : element;

    if (jQuery) {
      this.$element = jQuery(this.element);
    }

    // options
    this.options = extend({}, this.constructor.defaults);
    this.option(options);

    this._create();
  }

  // inherit Unidragger methods
  var proto = (Draggabilly.prototype = Object.create(Unidragger.prototype));

  Draggabilly.defaults = {};

  /**
   * set options
   * @param {Object} opts
   */
  proto.option = function(opts) {
    extend(this.options, opts);
  };

  // css position values that don't need to be set
  var positionValues = {
    relative: true,
    absolute: true,
    fixed: true
  };

  proto._create = function() {
    // properties
    this.position = {};
    this._getPosition();

    this.startPoint = { x: 0, y: 0 };
    this.dragPoint = { x: 0, y: 0 };

    this.startPosition = extend({}, this.position);

    // set relative positioning
    var style = getComputedStyle(this.element);
    if (!positionValues[style.position]) {
      this.element.style.position = "relative";
    }

    this.enable();
    this.setHandles();
  };

  /**
   * set this.handles and bind start events to 'em
   */
  proto.setHandles = function() {
    this.handles = this.options.handle
      ? this.element.querySelectorAll(this.options.handle)
      : [this.element];

    this.bindHandles();
  };

  /**
   * emits events via EvEmitter and jQuery events
   * @param {String} type - name of event
   * @param {Event} event - original event
   * @param {Array} args - extra arguments
   */
  proto.dispatchEvent = function(type, event, args) {
    var emitArgs = [event].concat(args);
    this.emitEvent(type, emitArgs);
    var jQuery = window.jQuery;
    // trigger jQuery event
    if (jQuery && this.$element) {
      if (event) {
        // create jQuery event
        var $event = jQuery.Event(event);
        $event.type = type;
        this.$element.trigger($event, args);
      } else {
        // just trigger with type if no event available
        this.$element.trigger(type, args);
      }
    }
  };

  // -------------------------- position -------------------------- //

  // get x/y position from style
  proto._getPosition = function() {
    var style = getComputedStyle(this.element);
    var x = this._getPositionCoord(style.left, "width");
    var y = this._getPositionCoord(style.top, "height");
    // clean up 'auto' or other non-integer values
    this.position.x = isNaN(x) ? 0 : x;
    this.position.y = isNaN(y) ? 0 : y;

    this._addTransformPosition(style);
  };

  proto._getPositionCoord = function(styleSide, measure) {
    if (styleSide.indexOf("%") != -1) {
      // convert percent into pixel for Safari, #75
      var parentSize = getSize(this.element.parentNode);
      // prevent not-in-DOM element throwing bug, #131
      return !parentSize
        ? 0
        : parseFloat(styleSide) / 100 * parentSize[measure];
    }
    return parseInt(styleSide, 10);
  };

  // add transform: translate( x, y ) to position
  proto._addTransformPosition = function(style) {
    var transform = style[transformProperty];
    // bail out if value is 'none'
    if (transform.indexOf("matrix") !== 0) {
      return;
    }
    // split matrix(1, 0, 0, 1, x, y)
    var matrixValues = transform.split(",");
    // translate X value is in 12th or 4th position
    var xIndex = transform.indexOf("matrix3d") === 0 ? 12 : 4;
    var translateX = parseInt(matrixValues[xIndex], 10);
    // translate Y value is in 13th or 5th position
    var translateY = parseInt(matrixValues[xIndex + 1], 10);
    this.position.x += translateX;
    this.position.y += translateY;
  };

  // -------------------------- events -------------------------- //

  /**
   * pointer start
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerDown = function(event, pointer) {
    this._dragPointerDown(event, pointer);
    // kludge to blur focused inputs in dragger
    var focused = document.activeElement;
    // do not blur body for IE10, metafizzy/flickity#117
    if (focused && focused.blur && focused != document.body) {
      focused.blur();
    }
    // bind move and end events
    this._bindPostStartEvents(event);
    this.element.classList.add("is-pointer-down");
    this.dispatchEvent("pointerDown", event, [pointer]);
  };

  /**
   * drag move
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerMove = function(event, pointer) {
    var moveVector = this._dragPointerMove(event, pointer);
    this.dispatchEvent("pointerMove", event, [pointer, moveVector]);
    this._dragMove(event, pointer, moveVector);
  };

  /**
   * drag start
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.dragStart = function(event, pointer) {
    if (!this.isEnabled) {
      return;
    }
    this._getPosition();
    this.measureContainment();
    // position _when_ drag began
    this.startPosition.x = this.position.x;
    this.startPosition.y = this.position.y;
    // reset left/top style
    this.setLeftTop();

    this.dragPoint.x = 0;
    this.dragPoint.y = 0;

    this.element.classList.add("is-dragging");
    this.dispatchEvent("dragStart", event, [pointer]);
    // start animation
    this.animate();
  };

  proto.measureContainment = function() {
    var containment = this.options.containment;
    if (!containment) {
      return;
    }

    // use element if element
    var container = isElement(containment)
      ? containment
      : // fallback to querySelector if string
        typeof containment == "string"
        ? document.querySelector(containment)
        : // otherwise just `true`, use the parent
          this.element.parentNode;

    var elemSize = getSize(this.element);
    var containerSize = getSize(container);
    var elemRect = this.element.getBoundingClientRect();
    var containerRect = container.getBoundingClientRect();

    var borderSizeX =
      containerSize.borderLeftWidth + containerSize.borderRightWidth;
    var borderSizeY =
      containerSize.borderTopWidth + containerSize.borderBottomWidth;

    var position = (this.relativeStartPosition = {
      x: elemRect.left - (containerRect.left + containerSize.borderLeftWidth),
      y: elemRect.top - (containerRect.top + containerSize.borderTopWidth)
    });

    this.containSize = {
      width: containerSize.width - borderSizeX - position.x - elemSize.width,
      height: containerSize.height - borderSizeY - position.y - elemSize.height
    };
  };

  // ----- move event ----- //

  /**
   * drag move
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.dragMove = function(event, pointer, moveVector) {
    if (!this.isEnabled) {
      return;
    }
    var dragX = moveVector.x;
    var dragY = moveVector.y;

    var grid = this.options.grid;
    var gridX = grid && grid[0];
    var gridY = grid && grid[1];

    dragX = applyGrid(dragX, gridX);
    dragY = applyGrid(dragY, gridY);

    dragX = this.containDrag("x", dragX, gridX);
    dragY = this.containDrag("y", dragY, gridY);

    // constrain to axis
    dragX = this.options.axis == "y" ? 0 : dragX;
    dragY = this.options.axis == "x" ? 0 : dragY;

    this.position.x = this.startPosition.x + dragX;
    this.position.y = this.startPosition.y + dragY;
    // set dragPoint properties
    this.dragPoint.x = dragX;
    this.dragPoint.y = dragY;

    this.dispatchEvent("dragMove", event, [pointer, moveVector]);
  };

  function applyGrid(value, grid, method) {
    method = method || "round";
    return grid ? Math[method](value / grid) * grid : value;
  }

  proto.containDrag = function(axis, drag, grid) {
    if (!this.options.containment) {
      return drag;
    }
    var measure = axis == "x" ? "width" : "height";

    var rel = this.relativeStartPosition[axis];
    var min = applyGrid(-rel, grid, "ceil");
    var max = this.containSize[measure];
    max = applyGrid(max, grid, "floor");
    return Math.min(max, Math.max(min, drag));
  };

  // ----- end event ----- //

  /**
   * pointer up
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.pointerUp = function(event, pointer) {
    this.element.classList.remove("is-pointer-down");
    this.dispatchEvent("pointerUp", event, [pointer]);
    this._dragPointerUp(event, pointer);
  };

  /**
   * drag end
   * @param {Event} event
   * @param {Event or Touch} pointer
   */
  proto.dragEnd = function(event, pointer) {
    if (!this.isEnabled) {
      return;
    }
    // use top left position when complete
    if (transformProperty) {
      this.element.style[transformProperty] = "";
      this.setLeftTop();
    }
    this.element.classList.remove("is-dragging");
    this.dispatchEvent("dragEnd", event, [pointer]);
  };

  // -------------------------- animation -------------------------- //

  proto.animate = function() {
    // only render and animate if dragging
    if (!this.isDragging) {
      return;
    }

    this.positionDrag();

    var _this = this;
    requestAnimationFrame(function animateFrame() {
      _this.animate();
    });
  };

  // left/top positioning
  proto.setLeftTop = function() {
    this.element.style.left = this.position.x + "px";
    this.element.style.top = this.position.y + "px";
  };

  proto.positionDrag = function() {
    this.element.style[transformProperty] =
      "translate3d( " + this.dragPoint.x + "px, " + this.dragPoint.y + "px, 0)";
  };

  // ----- staticClick ----- //

  proto.staticClick = function(event, pointer) {
    this.dispatchEvent("staticClick", event, [pointer]);
  };

  // ----- methods ----- //

  proto.enable = function() {
    this.isEnabled = true;
  };

  proto.disable = function() {
    this.isEnabled = false;
    if (this.isDragging) {
      this.dragEnd();
    }
  };

  proto.destroy = function() {
    this.disable();
    // reset styles
    this.element.style[transformProperty] = "";
    this.element.style.left = "";
    this.element.style.top = "";
    this.element.style.position = "";
    // unbind handles
    this.unbindHandles();
    // remove jQuery data
    if (this.$element) {
      this.$element.removeData("draggabilly");
    }
  };

  // ----- jQuery bridget ----- //

  // required for jQuery bridget
  proto._init = noop;

  if (jQuery && jQuery.bridget) {
    jQuery.bridget("draggabilly", Draggabilly);
  }

  // -----  ----- //

  return Draggabilly;
});
